package com.example.order.service.impl;

import com.example.common.context.BaseContext;
import com.example.common.domain.PageResult;
import com.example.common.domain.Result;
import com.example.common.exception.BizIllegalException;
import com.example.common.utils.RedisIdWorkUtil;
import com.example.order.constant.MQConstants;
import com.example.order.constant.OrderStatus;
import com.example.order.domain.dto.CreateOrderDTO;
import com.example.order.domain.dto.GoodsDTO;
import com.example.order.domain.dto.OrderListDTO;
import com.example.order.domain.po.Order;
import com.example.order.domain.po.OrderDetail;
import com.example.order.domain.vo.OrderListVO;
import com.example.order.domain.vo.OrderSkuVO;
import com.example.order.domain.vo.OrderVO;
import com.example.order.mapper.OrderDetailMapper;
import com.example.order.mapper.OrderMapper;
import com.example.order.service.OrderService;
import com.example.product.api.client.ProductClient;
import com.example.product.domain.dto.ItemDTO;
import com.example.product.domain.vo.ProductVO;
import com.example.user.api.client.AddressCLient;
import com.example.user.domain.vo.AddressVO;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import org.apache.seata.spring.annotation.GlobalTransactional;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;


@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
    private final ProductClient productClient;
    private final OrderMapper orderMapper;
    private final OrderDetailMapper orderDetailMapper;
    private final RedisIdWorkUtil redisIdWorkUtil;
    private final RedisTemplate redisTemplate;
    private final AddressCLient addressCLient;
    private final RabbitTemplate rabbitTemplate;

    private static final String KEY_ORDER_PAYMENT = "order:payment:";

    @Override
    @GlobalTransactional
    public Long createOrder(CreateOrderDTO createOrderDTO) {
        Long currentId = BaseContext.getCurrentId();
        List<GoodsDTO> goods = createOrderDTO.getGoods();


        // 生成订单号
        Long orderId = redisIdWorkUtil.nextId("order");

        List<OrderDetail> orderDetailList = new ArrayList<>();
        List<Long> itemIds = new ArrayList<>();
        List<ItemDTO> itemDTOList = new ArrayList<>();
        // 获取所有商品id
        goods.forEach(goodsDTO -> {
            Long itemId = goodsDTO.getItemId();
            // 收集商品id
            itemIds.add(itemId);
        });

        Result<Map<Long, ProductVO>> product = productClient.getProduct(itemIds);
        Map<Long, ProductVO> data = product.getData();
        // 创建订单详情对象
        goods.forEach(goodsDTO -> {
            // 创建订单详情号
            Long orderDetailId = redisIdWorkUtil.nextId("orderDetail");
            Long itemId = goodsDTO.getItemId();
            OrderDetail orderDetail = OrderDetail.builder()
                    .id(orderDetailId)
                    .orderId(orderId)
                    .productId(data.get(itemId).getProductId())
                    .itemId(itemId)
                    .num(goodsDTO.getNum())
                    .itemName(goodsDTO.getName())
                    .spec(goodsDTO.getSpec())
                    .price(goodsDTO.getPrice())
                    .image(goodsDTO.getImage())
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .build();
            // 存储订单详情对象
            orderDetailList.add(orderDetail);
            // 用于扣减库存
            itemDTOList.add(ItemDTO.builder()
                    .id(itemId)
                    .num(goodsDTO.getNum())
                    .build());
        });

        // 计算总金额
        BigDecimal totalFee = new BigDecimal(0);
        for (int i = 0; i < itemIds.size(); i++) {
            totalFee = totalFee.add(data.get(itemIds.get(i)).getPrice().multiply(new BigDecimal(goods.get(i).getNum())));
        }
        BigDecimal postFee = calculatePostFee(totalFee, goods.size());
        BigDecimal payMoney = totalFee.add(postFee);
        // 创建订单对象
        Order order = Order.builder()
                .id(orderId)
                .totalFee(totalFee)
                .postFee(postFee)
                .payMoney(payMoney)
                .paymentType(createOrderDTO.getPaymentType())
                .userId(currentId)
                .addressId(createOrderDTO.getAddressId())
                .buyerMessage(createOrderDTO.getBuyerMessage())
                .status(OrderStatus.UNPAID)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();

        // 保存订单
        orderMapper.insertOrder(order);
        // 保存订单详情
        orderDetailMapper.insertOrderDetail(orderDetailList);
        // 扣减库存
        Result result = productClient.deductStock(itemDTOList);
        if (result.getCode() == 0) {
            throw new BizIllegalException(result.getMsg());
        }


       /* redisTemplate.opsForValue().set(KEY_ORDER_PAYMENT + order.getId(),
                "pending",
                15, TimeUnit.MINUTES);*/
        redisTemplate.opsForValue().set(KEY_ORDER_PAYMENT + order.getId(),
                "pending",
                10000, TimeUnit.SECONDS);

        CorrelationData cd = new CorrelationData(UUID.randomUUID().toString());


        // 发送延迟消息
        rabbitTemplate.convertAndSend(MQConstants.DELAY_EXCHANGE_NAME,
                MQConstants.DELAY_ORDER_KEY, orderId,
                new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        //单位  ms
                        message.getMessageProperties().setDelayLong(10000L);
                        return message;
                    }
                },cd);

        return orderId;
    }

    /**
     * 获取订单详情
     *
     * @param id 订单id
     * @return 订单详情
     */
    @Override
    public OrderVO getOrderDetail(Long id) {
        Order order = orderMapper.selectOrderDetail(id);
        if (order != null) {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order, orderVO);
            // 获取订单支付倒计时
            // 返回正值：表示键的剩余生存时间(单位取决于参数)
            // 返回0：键存在但没有设置过期时间
            // 返回-1：键不存在
            // 返回-2：键已过期或被删除
            Long countdown = redisTemplate.getExpire(KEY_ORDER_PAYMENT + id);
            orderVO.setCountdown(countdown);

            // 根据addressId查询地址
            Integer addressId = order.getAddressId();
            Result<AddressVO> result = addressCLient.findById(addressId);
            AddressVO address = result.getData();
            // 设置收货地址
            orderVO.setReceiverAddress(address.getFullLocation() + address.getAddress());
            // 设置联系方式
            orderVO.setContact(address.getContact());
            // 设置收货人
            orderVO.setReceiver(address.getReceiver());
            List<OrderSkuVO> orderDetailList = orderDetailMapper.selectOrderDetailList(id);
            orderVO.setOrderSkuVOList(orderDetailList);
            return orderVO;
        }
        return null;
    }

    /**
     * 支付订单
     *
     * @param orderId 订单id
     */
    @Override
    public void payOrder(Long orderId) {
        Order order = Order.builder()
                .id(orderId)
                .status(OrderStatus.PENDING_SHIPMENT)
                .payTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();
        // 更新订单状态为已支付待发货
        orderMapper.updateOrderStatus(order);
        // 删除订单支付倒计时
        redisTemplate.delete(KEY_ORDER_PAYMENT + orderId);

    }

    /**
     * 收货完成，待评价
     *
     * @param orderId 订单id
     * @return 订单详情
     */
    @Override
    public OrderVO receiveOrder(Long orderId) {
        Order order = Order.builder()
                .id(orderId)
                .status(OrderStatus.PENDING_REVIEW)
                .updateTime(LocalDateTime.now())
                .build();
        orderMapper.updateOrderStatus(order);
        OrderVO orderVO = getOrderDetail(orderId);
        return orderVO;
    }

    /**
     * 删除订单
     *
     * @param ids 订单id列表
     */
    @Override
    public void deleteOrder(Long[] ids) {
        orderMapper.deleteOrder(ids);

    }

    /**
     * 获取订单列表
     *
     * @param page     页码
     * @param pageSize 页大小
     * @param status   订单状态
     * @return 订单列表
     */
    @Override
    public PageResult<OrderListVO> getOrderList(Integer page, Integer pageSize, Integer status) {
        Order order = Order.builder()
                .userId(BaseContext.getCurrentId())
                .status(status)
                .build();

        PageHelper.startPage(page, pageSize);
        Page<OrderListVO> pages = orderMapper.selectOrderList(order);
        List<OrderListVO> result = pages.getResult();
        result.forEach(orderListVO -> {
            List<OrderSkuVO> orderSkuVOS = orderDetailMapper.selectOrderDetailList(orderListVO.getId());
            Integer totalCount = 0;
            for (OrderSkuVO orderSkuVO : orderSkuVOS) {
                totalCount += orderSkuVO.getNum();
            }
            orderListVO.setTotalCount(totalCount);
            orderListVO.setOrderSkuVOList(orderSkuVOS);
        });
        PageResult<OrderListVO> pageResult = new PageResult<>(pages.getTotal(), pages.getResult());
        return pageResult;
    }

    /**
     * 取消订单
     *
     * @param orderId 订单id
     */
    @GlobalTransactional
    @Override
    public void cancelOrder(Long orderId) {
        Order order = Order.builder()
                .id(orderId)
                .status(6)
                .updateTime(LocalDateTime.now())
                .build();
        orderMapper.updateOrderStatus(order);

        List<OrderSkuVO> orderSkuVOS = orderDetailMapper.selectOrderDetailList(orderId);
        for (OrderSkuVO orderSkuVO : orderSkuVOS) {
            // 恢复库存
            productClient.restoreStock(Integer.valueOf(orderSkuVO.getItemId().toString()), orderSkuVO.getNum());
        }


    }

    /**
     * 计算订单邮费
     *
     * @param totalPrice   商品总价
     * @param productCount 商品总数量
     * @return 邮费金额
     */
    private BigDecimal calculatePostFee(BigDecimal totalPrice, Integer productCount) {
        // 基础邮费策略：满额免邮
        BigDecimal freeShippingThreshold = new BigDecimal("88.00"); // 满88元免邮
        BigDecimal basePostFee = new BigDecimal("8.00"); // 基础邮费8元

        // 如果订单金额达到免邮门槛，则免邮
        if (totalPrice.compareTo(freeShippingThreshold) >= 0) {
            return BigDecimal.ZERO;
        }

        // 按件数计算邮费（可选策略）
        // BigDecimal piecePostFee = new BigDecimal(productCount).multiply(new BigDecimal("2.00"));
        // return piecePostFee.max(basePostFee); // 取按件计算和基础邮费的较大值

        // 简单返回基础邮费
        return basePostFee;
    }
}
